package com.itheima.stock.service.impl;

import com.alibaba.excel.EasyExcel;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itheima.stock.Propertites.stockConfigProperties;
import com.itheima.stock.mapper.StockMarketIndexInfoMapper;
import com.itheima.stock.mapper.StockRtInfoMapper;
import com.itheima.stock.pojo.domain.InnerMarketDomain;
import com.itheima.stock.pojo.domain.StockBlockDomain;
import com.itheima.stock.pojo.domain.StockUpdownDomain;
import com.itheima.stock.pojo.domain.Stock4EvrDayDomain;
import com.itheima.stock.pojo.entity.Stock4MinuteDomain;
import com.itheima.stock.pojo.vo.updowncount;
import com.itheima.stock.service.StockService;
import com.itheima.stock.utils.DateTimeUtil;
import com.itheima.stock.vo.resp.PageResult;
import com.itheima.stock.vo.resp.R;
import com.itheima.stock.vo.resp.ResponseCode;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.ExecutionException;

@Service
@Slf4j
public class StockServiceImpl implements StockService {
    @Autowired
    stockConfigProperties configProperties;

    @Autowired
    StockMarketIndexInfoMapper stockMarketIndexInfoMapper;

    @Autowired
    StockRtInfoMapper stockRtInfoMapper;

    @Autowired
    Cache<String,Object> cache;
    /**
     * 获取当前时间的数据
     * @return
     */
    @Override


    public R<List<InnerMarketDomain>> innerIndexAll() throws ExecutionException {
        R<List<InnerMarketDomain>> object = (R<List<InnerMarketDomain>>) cache.get("Market", key -> {
            //1.获取国内A股大盘的id集合
            List<String> inners = configProperties.getInner();
            //2.获取最近股票交易日期
            Date lastDate = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();
                  //3.将获取的java Date传入接口
            List<InnerMarketDomain> list = stockMarketIndexInfoMapper.getMarketInfo(inners, lastDate);
            //4.返回查询结果
            return R.ok(list);
        });

        return object;
    }
    /**
     * 分页查询股票最新数据，并按照涨幅排序查询
     * @return
     */
    @Override
    public R<List<StockBlockDomain>> sectorAllLimit() {
        //获取股票最新交易时间点
        Date lastDate = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();
        //TODO mock数据,后续删除
        lastDate=DateTime.parse("2021-12-21 14:30:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //1.调用mapper接口获取数据
        List<StockBlockDomain> infos=stockMarketIndexInfoMapper.sectorAllLimit(lastDate);
        //2.组装数据
        //判断是否为空
        if (CollectionUtils.isEmpty(infos)) {
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
        return R.ok(infos);
    }

    @Override
    public R<PageResult<StockUpdownDomain>> getStockPageInfo(Integer page, Integer pageSize) {
        PageHelper.startPage(page,pageSize);
        Date curDate = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();
        //todo
        curDate= DateTime.parse("2022-06-07 15:00:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        List<StockUpdownDomain> infos= stockRtInfoMapper.getNewestStockInfo(curDate);
        if (CollectionUtils.isEmpty(infos)) {
            return R.error(ResponseCode.NO_RESPONSE_DATA);
        }
        PageResult<StockUpdownDomain> stockUpdownDomainPageResult = new PageResult<>(new PageInfo<StockUpdownDomain>(infos));

        return R.ok(stockUpdownDomainPageResult);
    }

    @Override
    public R<List<StockUpdownDomain>> getincrease() {
        Date curDate = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();
        //todo
        curDate= DateTime.parse("2022-06-07 15:00:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();

        List<StockUpdownDomain> list =  stockRtInfoMapper.getincrease(curDate);
        return R.ok(list);
    }

    @Override
    public R<List<updowncount>> getupdowncount() {
        Date curDate = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();
        //todo
        curDate= DateTime.parse("2021-12-30 09:33:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();

        List<updowncount> list = stockRtInfoMapper.getupdowncount(curDate);

        return R.ok(list);
    }

    @Override
    public void stockExport(HttpServletResponse response, Integer page, Integer pageSize) {

            R<PageResult<StockUpdownDomain>> stockPageInfo = this.getStockPageInfo(page, pageSize);

            List<StockUpdownDomain> rows = stockPageInfo.getData().getRows();


            //设置响应excel文件格式类型
            response.setContentType("application/vnd.ms-excel");
            //2.设置响应数据的编码格式
            response.setCharacterEncoding("utf-8");
            //3.设置默认的文件名称
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        try {
            //防止乱码
            String fileName = URLEncoder.encode("股票信息表", "UTF-8");
            //设置默认文件名称：兼容一些特殊浏览器
            //这里就是下载文件的名称并提示用户下载了，地址是浏览器默认的地址
            response.setHeader("content-disposition", "attachment;filename=" + fileName + ".xlsx");
            //4.响应excel流

            EasyExcel
                    .write(response.getOutputStream(),StockUpdownDomain.class)
                    .sheet("股票信息")
                    .doWrite(rows);
        } catch (IOException e) {
            response.setStatus(400);
            throw new RuntimeException(e);
        }


    }

    /**
     * @return
     */
    @Override
    public R<Map<String, List<updowncount>>> gettradeAmt() {
        //这里就是获取当前时间的结束时间
        DateTime TEndTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        Date Tend = TEndTime.toDate();


        //获取当前结束时间的开始时间，就是结束当天的上午开盘时间
        DateTime TStartTime = DateTimeUtil.getOpenDate(TEndTime);
        Date date = TStartTime.toDate();

        //获取当前结束时间的前一天当前时间的数据
        DateTime previousTradingDay = DateTimeUtil.getPreviousTradingDay(TEndTime);
        Date preTend = previousTradingDay.toDate();
        DateTime preTstart = DateTimeUtil.getOpenDate(previousTradingDay);

        Date predate = preTstart.toDate();
        //获取当前的结束时间的当天每分钟数据
  //      List<updowncount> data = stockRtInfoMapper.gettradeAmt(TStartTime,Tend,configProperties.getInner());

        //获取当前当天的前一天数据
   //     List<updowncount> predata = stockRtInfoMapper.gettradeAmt(preTstart,preTend,configProperties.getInner());

    Date  start = DateTime.parse("2021-12-28 09:31:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        Date  end = DateTime.parse("2021-12-28 14:28:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();

        List<updowncount> data = stockRtInfoMapper.gettradeAmt(start,end,configProperties.getInner());
        List<updowncount> predata = stockRtInfoMapper.gettradeAmt(start,end,configProperties.getInner());

        //封装数据
        Map<String,List<updowncount>> map = new HashMap<>();
        map.put("amtList",data);
        map.put("yesAmtList",predata);

        return R.ok(map);
    }

    @Override
    public R<Map> stockUpDownScopeCount() {
        //1.获取股票最新一次交易的时间点
        Date curDate = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();
        //mock data
        curDate=DateTime.parse("2022-01-06 09:55:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //2.查询股票信息
        List<Map> maps=stockRtInfoMapper.getStockUpDownSectionByTime(curDate);
        List<String> upDownRange = configProperties.getUpDownRange();

        List<Map> newmaps = new ArrayList<>();
        //这里就是补充没有的字段，并顺序化
        for (String s : upDownRange) {
            Map t = null;
            for (Map map : maps) {
                if (map.containsValue(s)){
                    t=map;
                    break;
                }

            }

            if (t==null)
            {
                t=new HashMap<>();
                t.put("count",0);
                t.put("title",s);
            }
            newmaps.add(t);
        }

        //3.组装数据
        HashMap<String, Object> mapInfo = new HashMap<>();
        //获取指定日期格式的字符串
        String curDateStr = new DateTime(curDate).toString(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"));
        mapInfo.put("time",curDateStr);
        mapInfo.put("infos",newmaps);
        //4.返回数据
        return R.ok(mapInfo);
    }

    @Override
    public R<List<Stock4MinuteDomain>> stockScreenTimeSharing(String stockcode) {
        //1.获取最近最新的交易时间点和对应的开盘日期
        //1.1 获取最近有效时间点
        DateTime lastDate4Stock = DateTimeUtil.getLastDate4Stock(DateTime.now());
        Date endTime = lastDate4Stock.toDate();
        //TODO mockdata
        endTime=DateTime.parse("2021-12-30 14:47:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();

        //1.2 获取最近有效时间点对应的开盘日期
        DateTime openDateTime = DateTimeUtil.getOpenDate(lastDate4Stock);
        Date startTime = openDateTime.toDate();
        //TODO MOCK DATA
        startTime=DateTime.parse("2021-12-30 09:30:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //2.根据股票code和日期范围查询
        List<Stock4MinuteDomain> list=stockRtInfoMapper.getStockInfoByCodeAndDate(stockcode,startTime,endTime);
        //判断非空处理
        if (CollectionUtils.isEmpty(list)) {
            list=new ArrayList<>();
        }
        //3.返回响应数据
        return R.ok(list);
    }

    @Override
    public R<List<Stock4EvrDayDomain>> stockCreenDkLine(String stockCode) {
        //1.获取查询的日期范围
        //1.1 获取截止时间
        DateTime endDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        Date endTime = endDateTime.toDate();
        //1.2 获取开始时间
        DateTime startDateTime = endDateTime.minusDays(10);
        Date startTime = startDateTime.toDate();
         //2.调用mapper接口获取查询的集合信息-方案1
        List<Date> end_time =  stockRtInfoMapper.getEndTime(stockCode,startTime,endTime);
        List<Stock4EvrDayDomain> data= stockRtInfoMapper.getStockInfo4EvrDay(end_time);
        //3.组装数据，响应
        return R.ok(data);
    }


}
